/**
 * Класс содержит данные о человеке (имя, фамилия, пол, дата рождения и дата смерти
 */

#ifndef _PERSON_H
#define	_PERSON_H

#include <iostream>
#include <string>
#include "common/Date.h"
#include "common/IllegalArgumentException.h"
#include "Gender.h"
#include "conf.h"

namespace etu {
namespace genealogy_tree {

using etu::common::Date;
using etu::common::IllegalArgumentException;

class Person {
    std::string firstName;
    std::string lastName;
    Gender gender;
    Date birthDate;
    Date deathDate;
    std::string description;
    std::string photoId;
    
public:
    Person(); // TODO

    /**
     * Создание объекта с заданными параметрами.
     * @param firstName имя
     * @param lastName фамилия
     * @param gender пол
     * @param birthDate дата рождения
     * @param deathDate дата смерти (может быть не задана)
     * @param description комментарии, описание для данного человека
     * @param photoId идентификатор фотографии данного человека
     * @throws IllegalArgumentException если не заданы имя или фаимилия;
     * если дата смерти раньше даты рождения
     */
    Person(const std::string& firstName, const std::string& lastName, Gender gender,
		const Date& birthDate, const Date& deathDate = Date::unkown(), 
                const std::string& description = "",
                const std::string& photoId = "") throw (IllegalArgumentException);

    /**
     * Конструктор копии
     */
    Person(const Person& orig);

    /**
     * Деструктор
     */
    virtual ~Person();

    /**
     * Создание неизвестного человека с неопределённым полом.
     * Используется тогда, когда данные о человеке неизвестны
     * @return человек с неизвестными данными
     */
    static Person unknown();

    /**
     * Создание неизвестного человека мужского пола.
     * Используется тогда, когда данные о человеке неизвестны
     * @return человек с неизвестными данными
     */
    static Person unknownMalePerson();

    /**
     * Создание неизвестного человека женского пола.
     * Используется тогда, когда данные о человеке неизвестны
     * @return человек с неизвестными данными
     */
    static Person unknownFemalePerson();

    /**
     * Проверка, классифицируется ли данный человек как неизвестный человек
     * @return true, если человек классифицируется как неизвестный человек; иначе false
     */
    static bool isUnkownPerson(const Person& person);

    virtual void setFirstName(const std::string& firstName);
    virtual void setLastName(const std::string& lastName);
    /**
     * Получение имени человека
     * @return имя
     */
    virtual const std::string& getFirstName() const;

    /**
     * Получение фамилии человека
     * @return фамилия
     */
    virtual const std::string& getLastName() const;

    /**
     * Получение пола человека
     * @return пол
     */
    virtual Gender getGender() const;
    virtual void setGender(Gender gender);

    /**
     * Получение даты рождения человека.
     * Если дата неизвестна, то метод Date::isUnknownDate() вернёт true
     * @return дата рождения
     */
    virtual const Date& getBirthDate() const;

    /**
     * Задание даты рождения человека
     * @param birthDate дата рождения
     */
    virtual void setBirthDate(const Date& birthDate);

    /**
     * Получение дата смерти человека.
     * Если дата неизвестна, то метод Date::isUnknownDate() вернёт true
     * @return дата смерти
     */
    virtual const Date& getDeathDate() const;

    /**
     * Задание даты смерти человека
     * @param deathDate дата смерти
     */
    virtual void setDeathDate(const Date& deathDate);

    /**
     * Получение пользовательского описания данного человека.
     * @return пользовательское описание данного человека
     */
    virtual const std::string& getDescription() const;

    /**
     * Задание пользовательского описания для данного человека
     * @param description пользовательское описание
     */
    virtual void setDescription(const std::string& description);

    virtual bool hasPhoto() const;

    /**
     * Получение идентификатора фотографии для данного человека
     * @return идентификатор фотографии для данного человека
     */
    virtual const std::string& getPhotoId() const;

    /**
     * Задание идентификатора фотографии для данного человека
     * @param id новый идентификатор фотографии
     */
    virtual void setPhotoId(const std::string& id);

    virtual bool isDead();

    bool operator==(const Person &person) const;
    bool operator!=(const Person &person) const;

    friend std::ostream& operator<<(std::ostream& os, const Person& person);
    friend std::ostream& operator<<(std::ostream& os, const Person* person);
    friend std::istream& operator>>(std::istream& is, Person& person);
    friend std::istream& operator>>(std::istream& is, const Person* person);
};

}
}

#endif	/* _PERSON_H */

